import { Effect, Reducer } from "umi";
import { queryPosts, votePost } from "@/services/post";
import { find, cloneDeep } from "lodash";

export interface Author {
  id: number;
  firstName: string;
  lastName: string;
}

export interface Post {
  id: number;
  title: string;
  votes: number;
}

export interface PostModelState {
  author?: Author;
  posts?: Post[];
}

export interface PostModelType {
  namespace: "post";
  state: PostModelState;
  effects: {
    fetch: Effect;
    vote: Effect;
  };
  reducers: {
    show: Reducer<PostModelState>;
    update: Reducer<PostModelState>;
  };
}

const PostModel: PostModelType = {
  namespace: "post",

  state: {
    author: {
      id: 1,
      firstName: "a",
      lastName: "b",
    },
    posts: [
      {
        id: 1,
        title: "abc",
        votes: 1,
      },
    ],
  },

  effects: {
    *fetch({ payload }, { call, put }) {
      const response = yield call(queryPosts, payload.value);
      yield put({
        type: "show",
        payload: response,
      });
    },
    *vote({ payload }, { call, put }) {
      const response = yield call(votePost, payload.value);
      yield put({
        type: "update",
        payload: response,
      });
    },
  },

  reducers: {
    show(state, action) {
      return {
        ...state,
        author: action.payload.data.author,
        posts: action.payload.data.author.posts || [],
      };
    },
    update(state, action) {
      const { posts } = state || { posts: [] };
      const { upvotePost } = action.payload.data;
      const item = find(posts, { id: upvotePost.id });
      let postsNew = posts;
      if (item) {
        item.votes = upvotePost.votes;
        postsNew = cloneDeep(posts);
      }
      return {
        ...state,
        posts: postsNew,
      };
    },
  },
};

export default PostModel;
